package org.miyuki4j.cfgtool;

import freemarker.template.Configuration;
import freemarker.template.Version;
import lombok.Getter;
import org.miyuki4j.cfgtool.exception.CommandParseException;

import java.io.File;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @Desc
 * @Author miyuki4j
 * @Date 2025/7/24/星期四 12:26
 * @Version 1.0
 */
public class TableConfig {
    private static final Map<ConfigKeyEnum, Object> CONFIGS = new LinkedHashMap<>();

    public static String getPackageName(TableMeta meta) {
        return get(ConfigKeyEnum.CODE_GENERATE_PACKAGE_PREFIX) + "." + meta.getModule();
    }

    public static String getClassName(TableMeta meta) {
        return getPackageName(meta) + "." + meta.getTableName();
    }

    public static void put(ConfigKeyEnum key, Object value) {
        CONFIGS.put(key, value);
    }

    public static <T> T get(ConfigKeyEnum key) {
        return (T) CONFIGS.getOrDefault(key, key.defValue);
    }

    public static <T> T get(ConfigKeyEnum key, T defaultValue) {
        return (T) CONFIGS.getOrDefault(key, defaultValue);
    }

    public static boolean has(ConfigKeyEnum key) {
        return CONFIGS.containsKey(key);
    }

    public static void replace(Map<ConfigKeyEnum, Object> configs) {
        CONFIGS.clear();
        CONFIGS.putAll(configs);
    }

    /**
     * @Desc
     * @Author miyuki4j
     * @Date 2025/7/24/星期四 12:54
     * @Version 1.0
     */
    @Getter
    public enum ConfigKeyEnum {

        ENCODING("encoding", "编码 默认值为UTF-8", false, "UTF-8"), // 编码

        // read
        INPUT_DIR("input_dir", "数据源目录 绝对路径") {
            @Override
            protected String doParse(String value) {
                if (StringUtils.isBlank(value)) {
                    throw new CommandParseException("数据源目录不能为空");
                }
                if (!new File(value).exists()) {
                    throw new CommandParseException("数据源目录不存在");
                }
                return value;
            }
        }, // 数据源目录

        // code generate
        CODE_GENERATE_DIR("code_generate_dir", "代码生成目录 绝对路径") {
            @Override
            protected String doParse(String value) {
                if (StringUtils.isBlank(value)) {
                    throw new CommandParseException("代码生成目录不能为空");
                }
                if (!new File(value).exists()) {
                    throw new CommandParseException("代码生成目录不存在");
                }
                return value;
            }
        }, // 源代码输出目录
        CODE_GENERATE_PACKAGE_PREFIX("code_generate_package_prefix", "代码生成包前缀"), // 包名前缀
        CODE_GENERATOR_TYPE("code_generator_type", "代码生成器类型 freemarker、 java 默认值为freemarker", false, CodeGeneratorEnum.FREEMARKER) {
            @Override
            protected CodeGeneratorEnum doParse(String value) {
                if (StringUtils.isBlank(value)) {
                    throw new CommandParseException("代码生成器类型不能为空");
                }
                CodeGeneratorEnum codeGeneratorEnum = CodeGeneratorEnum.of(value);
                if (Objects.isNull(codeGeneratorEnum)) {
                    throw new CommandParseException("代码生成器类型错误,value=" + value);
                }
                return codeGeneratorEnum;
            }
        }, // 代码生成器类型
        CODE_GENERATE_USE_LOMBOK("code_generate_use_lombok", "代码生成是否启用lombok, 默认值为false", false, false) {
            @Override
            protected Boolean doParse(String value) {
                return Boolean.parseBoolean(value);
            }
        }, // 是否使用lombok

        // export、import
        DATA_EXPORT_DIR("data_export_dir", "数据导出目录 绝对路径") {
            @Override
            protected String doParse(String value) {
                if (StringUtils.isBlank(value)) {
                    throw new CommandParseException("数据导出目录不能为空");
                }
                if (!new File(value).exists()) {
                    throw new CommandParseException("数据导出目录不存在");
                }
                return value;
            }
        }, //数据导出目录
        DATA_EXPORT_TYPE("data_export_type", "数据导出类型 json、xml, 默认值为json", false, TableDataExchangerEnum.JSON) {
            @Override
            protected TableDataExchangerEnum doParse(String value) {
                if (StringUtils.isBlank(value)) {
                    throw new CommandParseException("数据导出文件类型不能为空");
                }
                TableDataExchangerEnum exchangeType = TableDataExchangerEnum.of(value);
                if (Objects.isNull(exchangeType)) {
                    throw new CommandParseException(String.format("数据导出不支持文件类型：%s", value));
                }
                return exchangeType;
            }
        },//数据导出类型
        EXPORT_JSON_PRETTY("export_json_pretty", "导出json是否格式化, 默认值为false", false, false) {
            @Override
            protected Boolean doParse(String value) {
                return Boolean.parseBoolean(value);
            }
        }, // 导出json是否格式化
        DATA_IMPORT_DIR("data_import_dir", "数据导入目录") {
            @Override
            protected String doParse(String value) throws Exception {
                if (StringUtils.isBlank(value)) {
                    throw new Exception("数据导入目录不能为空");
                }
                if (!new File(value).exists()) {
                    throw new CommandParseException("数据导入目录不存在");
                }
                return value;
            }
        }, //数据导入目录
        DATA_IMPORT_TYPE("data_import_type", "数据导入文件类型 json、xml, 默认值为json", false, TableDataExchangerEnum.JSON) {
            @Override
            protected TableDataExchangerEnum doParse(String value) {
                if (StringUtils.isBlank(value)) {
                    throw new CommandParseException("数据导入文件类型不能为空");
                }
                TableDataExchangerEnum exchangeType = TableDataExchangerEnum.of(value);
                if (Objects.isNull(exchangeType)) {
                    throw new CommandParseException(String.format("数据导入不支持文件类型：%s", value));
                }
                return exchangeType;
            }
        }, //数据导入类型

        // freemarker
        FREEMARKER_VERSION("freemarker_version", "freemarker版本 默认值为2.3.32", false, Configuration.VERSION_2_3_32) {
            @Override
            protected Version doParse(String value) throws Exception {
                if (StringUtils.isBlank(value)) {
                    throw new CommandParseException("请输入freemarker版本");
                }
                return new Version(value);
            }
        }, // freemarker版本
        FREEMARKER_TEMPLATE_DIR("freemarker_template_dir", "freemarker模板目录 绝对路径 默认值为freemarker", false, "freemarker"), // freemarker模板目录
        FREEMARKER_TEMPLATE_NAME("freemarker_template_name", "freemarker模板文件名称 默认值为ConfigTemplate.ftl", false, "ConfigTemplate.ftl"), // freemarker模板名称
        FREEMARKER_FINAL_TEMPLATE_NAME("freemarker_template_name", "freemarker final模板文件名称 默认值为FinalConfigTemplate.ftl", false, "FinalConfigTemplate.ftl"), // freemarker final模板名称
        ;

        private final String value;
        private final String desc;
        private final boolean required;
        private Object defValue;

        ConfigKeyEnum(String value, String desc, boolean required) {
            this.value = value;
            this.desc = desc;
            this.required = required;
        }

        ConfigKeyEnum(String value, String desc, boolean required, Object defValue) {
            this(value, desc, required);
            this.defValue = defValue;
        }

        ConfigKeyEnum(String value, String desc) {
            this(value, desc, true);
        }

        public boolean match(String value) {
            return StringUtils.startsWith(value, "--" + this.value);
        }

        public final <T> T parse(final String value) {
            try {
                Objects.requireNonNull(value);
                int i = value.indexOf("=");
                String s = i > 0 ? value.substring(i + 1) : "";
                Object o = doParse(s);
                return (T) Objects.requireNonNull(o, "parse value npe, value=" + value);
            } catch (CfgToolException cte) {
                throw cte;
            } catch (Exception e) {
                throw new CommandParseException("value" + value, e);
            }
        }

        protected <T> T doParse(String value) throws Exception {
            return (T) value;
        }

        public String usage() {
            return "--" + value + ":" + (required ? "【必填】" : "【选填】") + "\t" + desc;
        }

        public String getArg() {
            return "--" + value;
        }

        public String getArg(Object value) {
            return "--" + this.value + "=" + value;
        }
    }

}
